package com.qdxwx.web.controller.ajax;

import com.alibaba.fastjson2.JSONObject;
import com.qdxwx.common.cache.CacheUtils;
import com.qdxwx.common.constants.CacheConstants;
import com.qdxwx.common.json.AjaxResult;
import com.qdxwx.common.utils.HttpUtils;
import com.qdxwx.common.utils.TKConvert;
import com.qdxwx.common.utils.TKString;
import com.qdxwx.data.service.website.WebsiteProfileService;
import com.qdxwx.models.user.User;
import com.qdxwx.web.utils.LoginUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import jakarta.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.Map;
import java.util.UUID;

/**
 * @author ZhiYong
 * @updateTime 2022/1/24 18:19
 * @description
 */
@RestController
@RequestMapping("/ajax/share")
public class AjaxShareController {
    private static final Logger logger = LoggerFactory.getLogger(AjaxShareController.class);
    @Autowired
    private WebsiteProfileService websiteProfileService;

    /**
     * 获取微信共享Sign
     */
    @RequestMapping("/create.json")
    @ResponseBody
    public AjaxResult createToken(HttpServletRequest request) {
        User user = LoginUser.getUser(request);
        if (user == null || user.getUserId() == 0) {
            return AjaxResult.auth("not login!");
        }
        //if (!WxLogin.isWxBrowser(request)) {
        //    return AjaxResult.error("不是微信浏览器，不支持此功能!");
        //}
        String url = TKString.trim(request.getParameter("url"));
        if (url.length() < 1) {
            logger.info("url:" + url);
            return AjaxResult.error("url 参数错误!");
        }
        url = TKConvert.toURLDecode(url);
        //logger.info("url:" + url);
        //获得 微信登录 配置
        Map<String, Object> wxConfig = websiteProfileService.getMap("wxLogin");
        String snsAppId = (String) wxConfig.get("snsAppId");
        String snsAppSecret = (String) wxConfig.get("snsAppSecret");

        if (TKString.isEmpty(snsAppId) || TKString.isEmpty(snsAppSecret)) {
            return AjaxResult.error("没有配置微信登录的公众号snsAppId和!snsAppSecret");
        }

        String nonceStr = create_nonce_str();
        String timeStamp = create_timestamp();
        //注意这里参数名必须全部小写，且必须有序
        String jsapi_ticket = getTicket(snsAppId, snsAppSecret);
        if (jsapi_ticket == null) {
            return AjaxResult.error("获取jsapi_ticket错误！");
        }
        String string1 = "jsapi_ticket=" + jsapi_ticket +
                "&noncestr=" + nonceStr +
                "&timestamp=" + timeStamp +
                "&url=" + url;

        logger.info("string1:"+ string1);

        String signature = getSignature(string1);

        AjaxResult ret = AjaxResult.success("success");
        //ret.put("url", url);
        ret.put("appId", snsAppId);
        //ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonceStr);
        ret.put("timeStamp", timeStamp);
        ret.put("signature", signature);
        //logger.info("ret:" + ret);
        return ret;
    }

    private String getSignature(String signStr) {
        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(signStr.getBytes(StandardCharsets.UTF_8));
            return byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            logger.error("signStr:" + signStr);
            return null;
        }
    }

    private String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    private String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    private String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

    public static String getTicket(String appId, String appSecret) {
        String cacheKey = CacheConstants.NAME_SPACE + ":wxShare:ticket";
        String ticket = (String) CacheUtils.get(cacheKey);
        if (ticket != null) {
            return ticket;
        }
        String access_token = getAccessToken(appId, appSecret);
        if (access_token==null){
            return null;
        }
        logger.info("access_token:" + access_token);
        //https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket" +
                "?access_token=" + access_token +
                "&type=jsapi";
        JSONObject ret = JSONObject.parseObject(HttpUtils.doGet(url));
        if (ret != null) {
            ticket = (String) ret.get("ticket");
            long expires_in = TKConvert.toLong(ret.get("expires_in"));
            if (ticket != null && expires_in > 0) {
                CacheUtils.set(cacheKey, ticket, expires_in);
                return ticket;
            } else {
                logger.error("getTicket error");
                logger.error(ret.toJSONString());
            }
        }
        return null;
    }

    public static String getAccessToken(String appId, String appSecret) {
        String cacheKey = CacheConstants.NAME_SPACE + ":wxShare:accessToken";
        String access_token = (String) CacheUtils.get(cacheKey);
        if (access_token != null) {
            return access_token;
        }
        //https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" +
                "&appid=" + appId +
                "&secret=" + appSecret;
        JSONObject ret = JSONObject.parseObject(HttpUtils.doGet(url));
        if (ret != null) {
            access_token = (String) ret.get("access_token");
            long expires_in = TKConvert.toLong(ret.get("expires_in"));
            if (access_token != null && expires_in > 0) {
                CacheUtils.set(cacheKey, access_token, expires_in);
                return access_token;
            } else {
                logger.error("getAccessToken error");
                logger.error(ret.toJSONString());
            }
        }
        return null;
    }
}
